from PIL import Image, ImageFilter, ImageDraw
import cv2


def PIL_using(image):
    # 彩色读取
    img = cv2.imread(image, cv2.IMREAD_COLOR)
    # 展示图片
    cv2.imshow('image_show', img)
    cv2.waitKey(0)

    # 灰度读取
    img2 = cv2.imread(image, cv2.IMREAD_GRAYSCALE)
    cv2.imshow('image_show', img2)
    cv2.waitKey(0)

    # PIL 模块可以从图片获得图片每个像素点的颜色信息
    # 打开要处理的图像
    image = Image.open(image)
    # 转换图片的模式为YCbCr
    image = image.convert('YCbCr')
    # 获得文字图片的每个像素点
    strlist = image.load()
    # 100,100 是像素点的坐标
    data = strlist[100, 100]
    # 结果data是一个元组包含这个像素点的颜色信息    栗子：(0, 0, 0, 255)
    print(data)
    # 图片展示
    # image.show()

    # 图片的大小尺寸
    print(image.size)
    xsiez, ysize = image.size
    print(xsiez)
    print(ysize)
    # 生成缩略图
    image.thumbnail((xsiez//2, ysize//2))
    print(image.size)
    # 图片保存
    image.save('thumbPicture.jpg', 'JPEG')
    # 生成缩略图
    image = image.resize((image.size[0]//2, image.size[1]//2))
    # 使用rotate 方法将图片旋转90度
    out = image.rotate(90)
    out.save('out.jpg', 'JPEG')

    # transpose 方法对图片进行上下翻转，左右翻转，旋转等操作
    out = image.transpose(Image.FLIP_LEFT_RIGHT)  # 左右翻转
    out.show()
    out = image.transpose(Image.FLIP_TOP_BOTTOM)  # 上下翻转
    out.show()
    out = image.transpose(Image.ROTATE_180)  # 旋转180°
    out.show()
    image.show()


# 截取图片并实现将图片沿X 方向滑动的效果
def roll_x_size(image, delta):
    image = Image.open(image)
    xsize, ysize = image.size
    delta = delta % xsize
    if delta == 0:
        image.show()
    part1 = image.crop((0, 0, delta, ysize))
    part2 = image.crop((delta, 0, xsize, ysize))
    image.paste(part2, (0, 0, xsize-delta, ysize))
    image.paste(part1, (xsize-delta, 0, xsize, ysize))
    image.show()


# 截取图片并实现将图片沿着Y 方向滑动的效果
def roll_y_size(image, delta):
    image = Image.open(image)
    xsize, ysize = image.size
    delta = delta % xsize
    if delta == 0:
        image.show()
    part1 = image.crop((0, 0, xsize, delta))
    part2 = image.crop((0, delta, xsize, ysize))
    image.paste(part2, (0, 0, xsize, ysize-delta))
    image.paste(part1, (0, ysize-delta,  xsize, ysize))
    image.show()


# 将彩色图片分开成单个通道再合并
def split_channel(image):
    image = Image.open(image)
    # image.show()
    # 分离成单个通道
    r, g, b = image.split()
    r.show()
    g.show()
    b.show()
    # 合并成一张新的图片
    image = Image.merge('RGB', (b, r, g))
    image.show()


# 颜色变换：将彩色图片转换为灰度图
def change_color(image):
    image = Image.open(image)
    # 将RGB格式的图片转换为灰度图
    image = image.convert('L')
    # 通过对象属性检查文件内容
    print(image.mode, image.format, image.size)
    # image.show()
    print(image.info)
    # format属性定义了图像的格式（PNG, JPG, None），如果图像不是从文件打开的，那么该属性值为 None；
    # size 属性是一个二元 tuple，表示图像的宽和高（单位为像素 px）；
    # mode 属性为表示图像的模式，常用的模式为：L （luminance）为灰度图，RGB 为真彩色，CMYK 为 pre-press 图像。
    # palette: 仅当 mode 为 P 时有效，返回 ImagePalette 实例
    # info: 以字典的形式返回实例的信息


# 图像滤波
def image_filtering(image):
    image = Image.open(image)
    out = image.filter(ImageFilter.DETAIL)  # 细节增强
    out.show()
    out = image.filter(ImageFilter.BLUR)  # 模糊化
    out.show()
    out = image.filter(ImageFilter.CONTOUR)  # 轮廓滤波，将图片的轮廓提取出来
    out.show()
    out = image.filter(ImageFilter.EDGE_ENHANCE)  # 边缘强化
    out.show()
    # 深度边缘增强滤波，会使得图像中边缘部分更加明显
    out = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
    out.show()
    out = image.filter(ImageFilter.EMBOSS)  # 浮雕滤波，会使图像呈现出浮雕效果
    out.show()
    out = image.filter(ImageFilter.SMOOTH)  # 平滑滤波
    out.show()


# crop() 方法可以从图像中提取一个子矩形选区,矩形选区区域由一个 4 元元组决定，元组信息表示 (左,上,右,下) 的坐标。Pillow 库以图像左上角为坐标原点 (0,0)，单位是 px 。
def crop_fun(image):
    image = Image.open(image)
    box = (150, 150, 450, 450)
    region = image.crop(box)
    region.show()
    # 处理子图，粘贴回原图
    region = region.transpose(Image.ROTATE_270)
    # paste() 方法则可以将一个 Image 实例粘贴到另一个 Image 实例上
    image.paste(region, box)
    image.show()


def roll(image, delta):
    image = Image.open(image)
    xsize, ysize = image.size

    delta = delta % xsize  # 翻卷多少像素
    if delta == 0:
        image.show()   # 不翻卷图形

    part1 = image.crop((0, 0, delta, ysize))  # 左边矩形选区
    part2 = image.crop((delta, 0, xsize, ysize))  # 右边矩形选区
    part1.load()
    part2.load()
    image.paste(part2, (0, 0, xsize-delta, ysize))  # 原右边图形贴到左边
    image.paste(part1, (xsize-delta, 0, xsize, ysize))  # 原左边图形贴到右边
    image.show()


# Draw 类中的基本绘画操作函数：
# 弦/弧/扇形: chord / arc / pieslice、椭圆: ellipse、线段/多段线: line、点: point
# 多边形: polygon、矩形: rectangle、文字: text、文字大小: textsize
# Draw 类提供了 line(xy, options) 函数绘制直线。 其中 xy 表示坐标列表，它可以是任何包含 2 元组[(x, y), …] 或者数字[x, y, …] 的序列对象，至少包含两个坐标：
# options 可用的选项：fill = (R, G, B) ：指定线条颜色、width = integer ：指定线条宽度，单位是px
def draw_using(image):
    image = Image.open(image)
    drawAvatar = ImageDraw.Draw(image)
    xSize, ySize = image.size
    # 三等分位置画直线
    drawAvatar.line([0, 0.33*ySize, xSize, 0.33*ySize],
                    fill=(255, 0, 0), width=3)
    # 左下角到中心点，右下角到中心点
    drawAvatar.line([(0, ySize), (0.5 * xSize, 0.5 * ySize),
                    (xSize, ySize)], fill=(255, 0, 0), width=3)
    image.show()
    image.save('newImage.jpg')
    pass


if __name__ == '__main__':
    image = 'picture.jpg'
    PIL_using(image)
    roll_x_size(image, 200)
    roll_y_size(image, 200)
    split_channel(image)
    change_color(image)
    image_filtering(image)
    crop_fun(image)
    roll(image, 200)
    draw_using(image)
